package cn.well.cloud.quartz.modular.controller;

import cn.hutool.core.util.StrUtil;
import cn.stylefeng.roses.core.base.controller.BaseController;
import cn.stylefeng.roses.core.util.ToolUtil;
import cn.stylefeng.roses.kernel.model.exception.ServiceException;
import cn.stylefeng.roses.kernel.model.response.ResponseData;
import cn.well.cloud.base.auth.annotion.Permission;
import cn.well.cloud.base.pojo.page.LayuiPageFactory;

import cn.well.cloud.base.util.DateUtil;
import cn.well.cloud.quartz.core.model.ScheduleJob;
import cn.well.cloud.quartz.core.task.api.JobOperationAPI;
import cn.well.cloud.quartz.core.task.util.CronUtil;
import cn.well.cloud.sys.core.exception.enums.BizExceptionEnum;
import cn.well.cloud.sys.core.log.LogObjectHolder;
import cn.well.cloud.quartz.modular.model.Timetask;
import cn.well.cloud.quartz.modular.model.status.TimetaskJobStatus;
import cn.well.cloud.quartz.modular.service.ITimetaskService;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.quartz.CronExpression;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.*;

/**
 * 管理端使用
 *
 * 定时任务控制器
 *
 * @author jiawei
 * @Date 2020-06-30 11:05:27
 */
@Controller
@RequestMapping("/timetask")
@Slf4j
public class TimetaskAdminController extends BaseController {

    private String PREFIX = "/modular/task/timetask/";

    @Autowired
    private ITimetaskService timetaskService;

    @Autowired
    private JobOperationAPI jobOperationAPI;

    /**
     * 跳转到定时任务首页
     */
    @RequestMapping("")
    public String index() {
        return PREFIX + "timetask.html";
    }

    /**
     * 跳转到添加定时任务
     */
    @RequestMapping("/timetask_add")
    public String timetaskAdd() {
        return PREFIX + "timetask_add.html";
    }

    /**
     * 跳转到编辑定时任务
     */
    @RequestMapping("/timetask_edit")
    public String timetaskEdit(@RequestParam Long taskId) {
		if (ToolUtil.isEmpty(taskId)) {
            throw new ServiceException(BizExceptionEnum.REQUEST_NULL);
        }
        Timetask timetask = timetaskService.getById(taskId);
        LogObjectHolder.me().set(timetask);
        return PREFIX + "timetask_edit.html";
    }

    /**
     * 获取定时任务列表
     */
    @RequestMapping(value = "/list")
    @ResponseBody
    public Object list(@RequestParam(value = "timetaskName", required = false) String timetaskName
        ,@RequestParam(value = "description", required = false) String description) {
    
    	Page page = LayuiPageFactory.defaultPage();
    	QueryWrapper<Timetask> queryWrapper = new QueryWrapper<Timetask>();
    	if(StrUtil.isNotEmpty(timetaskName)){
            queryWrapper.and(wrapper -> wrapper.like("name", timetaskName).or().like("description", description));
        }
    	IPage<Map<String, Object>> pageInfo = timetaskService.pageMaps(page, queryWrapper);
        List<Map<String, Object>> dataList = pageInfo.getRecords();


        // 查询task的运行状态

        Object result =  jobOperationAPI.getRunningJob();
        if(result!=null){
            JSONObject jsonResult = (JSONObject) JSON.toJSON(result);
            Map<String, ScheduleJob> map = new HashMap<String, ScheduleJob>();
            if( jsonResult.getIntValue("code")==200){
                String dataStr = jsonResult.getString("data");
                List<ScheduleJob> jobList =  JSONArray.parseArray(dataStr,ScheduleJob.class);
                for(ScheduleJob job: jobList){
                    if(StrUtil.isNotEmpty(job.getJobId())){
                        map.put(job.getJobId().toString(), job);
                    }
                }
            }
            for(Map<String, Object> m: dataList){
                Timetask st = JSONObject.parseObject(JSONObject.toJSONString(m), Timetask.class);
                if(map.containsKey( String.valueOf(st.getTaskId()))){
                    m.put("concurrent",1);
                }
            }
        }
        // 查询task的计划状态
        Object planResult =  jobOperationAPI.getAllJob();
        if(planResult!=null){
            JSONObject jsonPlanResult =  (JSONObject) JSON.toJSON(planResult);
            Map<String, ScheduleJob> planMap = new HashMap<String, ScheduleJob>();
            if(jsonPlanResult.getIntValue("code")==200){
                String dataStr = jsonPlanResult.getString("data");
                List<ScheduleJob> jobList =  JSONArray.parseArray(dataStr,ScheduleJob.class);
                for(ScheduleJob job: jobList){
                    if(StrUtil.isNotEmpty(job.getJobId())) {
                        planMap.put(job.getJobId().toString(), job);
                    }
                }
            }
            for(Map<String, Object> m: dataList){
                Timetask st = JSONObject.parseObject(JSONObject.toJSONString(m), Timetask.class);
                if(planMap.containsKey( String.valueOf(st.getTaskId()))){
                    String status = planMap.get(String.valueOf(st.getTaskId())).getJobStatus();
                    m.put("planStatus",status);
                }else{
                    m.put("planStatus","NONE"); //不存在
                }
            }
        }
        pageInfo.setRecords(dataList);
        return LayuiPageFactory.createPageInfo(pageInfo);
    }

    /**
     * 立即执行一次job
     * 用于测试任务是否正确
     * @param taskId
     * @return
     */
    @RequestMapping(value="/planJobRun")
    @ResponseBody
    public Object planJobRun(@RequestParam("taskId") Long taskId){
        Timetask timetask = timetaskService.getById(taskId);
        if(timetask !=null){
            String name  = timetask.getName();
            String  groupName = timetask.getGroupName();
            Object result =  jobOperationAPI.runAJobNow(name , groupName);
            JSONObject jsonResult = (JSONObject) JSON.toJSON(result);
            if( jsonResult.getIntValue("code")==200){
                return SUCCESS_TIP;
            } else{
                return ResponseData.error("执行失败");
            }
        }
        return ResponseData.error("数据不存在");
    }

    /**
     * 添加job到计划列表
     * @param taskId
     * @return
     */
    @RequestMapping(value="/planJobAdd")
    @ResponseBody
    public Object planJobAdd(@RequestParam("taskId") Long taskId){
        Timetask timetask = timetaskService.getById(taskId);
        if(timetask !=null){
            Object result =  jobOperationAPI.addJob(timetask);
            JSONObject jsonResult = (JSONObject) JSON.toJSON(result);
            if( jsonResult.getIntValue("code")==200){
                return SUCCESS_TIP;
            } else{
                return ResponseData.error("添加失败");
            }
        }
        return ResponseData.error("数据不存在");
    }

    /**
     * 从计划列表中暂停job
     * @param taskId
     * @return
     */
    @RequestMapping(value="/planJobStop")
    @ResponseBody
    public Object planJobStop(@RequestParam("taskId") Long taskId){
        Timetask timetask = timetaskService.getById(taskId);
        if(timetask !=null){
            String name  = timetask.getName();
            String  groupName = timetask.getGroupName();
            Object result =  jobOperationAPI.pauseJob(name , groupName);
            JSONObject jsonResult = (JSONObject) JSON.toJSON(result);
            if( jsonResult.getIntValue("code")==200){
                return SUCCESS_TIP;
            } else{
                return ResponseData.error("暂停失败");
            }
        }
        return ResponseData.error("数据不存在");
    }

    /**
     * 从计划列表中移除job
     * @param taskId
     * @return
     */
    @RequestMapping(value="/planJobRemove")
    @ResponseBody
    public Object planJobRemove(@RequestParam("taskId") Long taskId){
        Timetask timetask = timetaskService.getById(taskId);
        if(timetask !=null){
            String name  = timetask.getName();
            String  groupName = timetask.getGroupName();
            Object result =  jobOperationAPI.deleteJob(name , groupName);
            JSONObject jsonResult = (JSONObject) JSON.toJSON(result);
            if( jsonResult.getIntValue("code")==200){
                return SUCCESS_TIP;
            } else{
                return ResponseData.error("暂停失败");
            }
        }
        return ResponseData.error("数据不存在");
    }

    /**
     * 启用/禁言job
     * @param taskId
     * @param type
     * @return
     */
    @RequestMapping(value="/changeJobStatus")
    @ResponseBody
    public Object changeJobStatus(@RequestParam("taskId") String taskId, String type){
        Timetask timetask = timetaskService.getById(taskId);
        if(timetask !=null){
            if(TimetaskJobStatus.ENABLE.getCode().equals(type)){
                timetask.setJobStatus(TimetaskJobStatus.ENABLE.getCode());
                jobOperationAPI.addJob(timetask);
            } else if(TimetaskJobStatus.DISABLE.getCode().equals(type)){
                String name  = timetask.getName();
                String  groupName = timetask.getGroupName();
                jobOperationAPI.deleteJob(name , groupName);
                timetask.setJobStatus(TimetaskJobStatus.DISABLE.getCode());
            }
        }
       timetaskService.updateById(timetask);
        return SUCCESS_TIP;
    }

    /**
     * 校验job的组+名称是否唯一
     * @param taskId
     * @param name
     * @param groupName
     * @return
     */
    @RequestMapping(value="/checkName")
    @ResponseBody
    public Object checkName(@RequestParam(value = "taskId", required = false)String taskId,
                            @RequestParam(value = "name", required = true)String name,
                            @RequestParam(value = "groupName", required = true)String groupName){
        QueryWrapper<Timetask> queryWrapper = new QueryWrapper<Timetask>();
        Timetask task = new Timetask();

        if(StrUtil.isNotEmpty(taskId)){
            queryWrapper.and(wrapper -> wrapper.ne("task_id", taskId));
        }
        queryWrapper.and(wrapper -> wrapper.eq("name", name).eq("group_name", groupName));
        List<Timetask> dataList = timetaskService.list(queryWrapper);
        if(dataList !=null && dataList.size() >0){
            return ResponseData.success(true);
        }else{
            return ResponseData.success(false);
        }
    }

    /**
     * 校验job的cron表达式
     * @param cron
     * @return
     */
    @RequestMapping(value="/checkCron")
    @ResponseBody
    public Object checkCron(@RequestParam(value = "cron", required = true)String cron){
        Boolean result = CronExpression.isValidExpression(cron);
        return ResponseData.success(result);
    }

    /**
     * 解析cron表达式
     * @param cron
     * @return
     */
    @RequestMapping(value = "/analysisCron")
    @ResponseBody
    public Object analysisCron(@RequestParam(value = "cron", required = true)String cron ) {
        String dateStr = DateUtil.formatStandardDatetime(new Date());
        try {
            Boolean check = CronExpression.isValidExpression(cron);
            if(!check){
                log.error("cron 表达式格式错误");
                return ResponseData.error("cron 表达式格式错误");
            }
            List<Map<String, Object>> dataList = CronUtil.cronAlgBuNums(cron, dateStr, 7);
            IPage<Map<String, Object>> pageInfo = new Page<>();
            pageInfo.setRecords(dataList);
            pageInfo.setTotal(7);
            return LayuiPageFactory.createPageInfo(pageInfo);
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseData.error("解析出错");
        }

    }

    /**
     * 添加定时任务
     */
    @Permission
	@RequestMapping(value = "/add")
    @ResponseBody
    public Object add(Timetask timetask) {
        timetask.setConcurrent(0);
        timetask.setJobStatus(TimetaskJobStatus.DISABLE.getCode());
        timetaskService.save(timetask);
        return SUCCESS_TIP;
    }

    /**
     * 删除定时任务
     */
    @Permission
    @RequestMapping(value = "/delete")
    @ResponseBody
    public Object delete(@RequestParam Long taskId) {
        timetaskService.removeById(taskId);
        return SUCCESS_TIP;
    }

    /**
     * 修改定时任务
     */
    @Permission
    @RequestMapping(value = "/edit")
    @ResponseBody
    public Object edit(Timetask timetask) {
        timetaskService.updateById(timetask);
        return SUCCESS_TIP;
    }

    /**
     * 定时任务详情
     */
    @RequestMapping(value = "/detail")
    @ResponseBody
    public Object detail(@RequestParam("taskId") Long taskId) {
    	Timetask timetask = timetaskService.getById(taskId);
    	return ResponseData.success(timetask);
    }

}
